
#include <stdio.h>
#include <stdlib.h>
#include "converse.h"
#include "charmProjections.h"
#include "traceCoreCommon.h"
#include "charmEvents.h"
#include "ck.h"
#include "trace-common.h" // for _threadEP

#if CMK_TRACE_ENABLED
CtvStaticDeclare(int,curThreadEvent);

static int curEvent;
static int execEvent;
static int execEp;
static int execPe;
static int curevent=0;
#endif

void initCharmProjections() 
{
#if CMK_TRACE_ENABLED
  CtvInitialize(int,curThreadEvent);
  CtvAccess(curThreadEvent) = 0;
  curEvent = 0;
#endif
}

//TODO
//int  traceRegisterUserEvent(const char*) 
//{return -1;}	

void charm_creation(envelope *e, int ep, int num)
{
#if CMK_TRACE_ENABLED
  if(e==0) {
    CtvAccess(curThreadEvent)=curEvent;
	int iData[4];
	iData[0] = ForChareMsg;
	iData[1] = ep;
	iData[2] = curEvent++;
	iData[3] = CkMyPe();
	LogEvent1(_CHARM_LANG_ID, _E_CREATION, 4, iData); 
  } else {
    e->setEvent(curEvent);
    for(int i=0; i<num; i++) {
		int iData[5];
		iData[0] = e->getMsgtype();
		iData[1] = ep;
		iData[2] = curEvent+i;
		iData[3] = CkMyPe();
		iData[4] = e->getTotalsize();
		LogEvent1(_CHARM_LANG_ID, _E_CREATION, 5, iData); 
    }
    curEvent += num;
  }
#endif
}

void charm_beginExecute(envelope *e)
{
#if CMK_TRACE_ENABLED
  if(e==0) {
    execEvent = CtvAccess(curThreadEvent);
    execEp = (-1);
	int iData[4];
	iData[0] = ForChareMsg;
	iData[1] = _threadEP;
	iData[2] = execEvent;
	iData[3] = CkMyPe();
	LogEvent1(_CHARM_LANG_ID, _E_BEGIN_PROCESSING, 4, iData); 
  } else {
    charm_beginExecuteDetailed(e->getEvent(),e->getMsgtype(),e->getEpIdx(),e->getSrcPe(),e->getTotalsize());
  }
#endif
}

void charm_beginExecuteDetailed(int event,int msgType,int ep,int srcPe,int ml)
{
#if CMK_TRACE_ENABLED
  execEvent=event;
  execEp=ep;
  execPe=srcPe;
  int iData[5];
  iData[0] = msgType;
  iData[1] = ep;
  iData[2] = event;
  iData[3] = srcPe;
  iData[4] = ml;
 // CkPrintf("iData in beginExecuteDetailed %d %d \n",event,srcPe);
  LogEvent1(_CHARM_LANG_ID, _E_BEGIN_PROCESSING, 5, iData); 
#endif
}

void charm_endExecute(void)
{
#if CMK_TRACE_ENABLED
  if(execEp == (-1)) {
	int iData[4];
	iData[0] = 0;
	iData[1] = _threadEP;
	iData[2] = execEvent;
	iData[3] = CkMyPe();
	LogEvent1(_CHARM_LANG_ID, _E_END_PROCESSING, 4, iData); 
  } else {
	int iData[4];
	iData[0] = 0;
	iData[1] = execEp;
	iData[2] = execEvent;
	iData[3] = execPe;
	LogEvent1(_CHARM_LANG_ID, _E_END_PROCESSING, 4, iData); 
  }
#endif
}

// implementing enqueue and dequeue --schak 
// however these type of events are not generated by anyone

void charm_enqueueMsg(envelope *e) {
#if CMK_TRACE_ENABLED
	int iData[3];
	iData[0] = e->getMsgtype();
	iData[1] = e->getEvent();
	iData[2] = e->getSrcPe();
	LogEvent1(_CHARM_LANG_ID,_E_ENQUEUE,3,iData);
#endif
}	

void charm_dequeueMsg(envelope *e) {
#if CMK_TRACE_ENABLED
	int iData[3];
	iData[0] = e->getMsgtype();
	iData[1] = e->getEvent();
	iData[2] = e->getSrcPe();
	LogEvent1(_CHARM_LANG_ID,_E_DEQUEUE,3,iData);
#endif
}	

void charm_beginComputation(void)
{
#if CMK_TRACE_ENABLED
	LogEvent1(_CHARM_LANG_ID, _E_BEGIN_COMPUTATION, 0, NULL); 
#endif
}

void charm_endComputation(void)
{
#if CMK_TRACE_ENABLED
	LogEvent1(_CHARM_LANG_ID, _E_END_COMPUTATION, 0, NULL); 
#endif
}

void charm_messageRecv(char *env, int pe) {} //TODO

void charm_userEvent(int e) {
#if CMK_TRACE_ENABLED
	int iData[3];
	iData[0] = e;
	iData[1] = curevent;
	iData[2] = CkMyPe();
	curevent++;
	LogEvent1(_CHARM_LANG_ID, _E_USER_EVENT_CHARM,3,iData);
#endif
}	


void charm_userPairEvent(int e,double bt,double et){
#if CMK_TRACE_ENABLED
	int iData1[3];
	int iData2[3];
	iData1[0] = iData2[0] = e;
	iData1[1] = iData2[1] = curevent;
	iData1[2] = iData2[2] = CkMyPe();
	curevent++;
	LogEvent4(_CHARM_LANG_ID, _E_USER_EVENT_PAIR,3,iData1,bt);
	LogEvent4(_CHARM_LANG_ID, _E_USER_EVENT_PAIR,3,iData2,et);
	
#endif
}

void charm_beginPack(void)
{
#if CMK_TRACE_ENABLED
	int iData[1];
	iData[0] = CkMyPe();
	LogEvent1(_CHARM_LANG_ID, _E_BEGIN_PACK, 1, iData); 
#endif
}

void charm_endPack(void)
{
#if CMK_TRACE_ENABLED
	int iData[1];
	iData[0] = CkMyPe();
	LogEvent1(_CHARM_LANG_ID, _E_END_PACK, 1, iData); 
#endif
}

void charm_beginUnpack(void)
{
#if CMK_TRACE_ENABLED
	int iData[1];
	iData[0] = CkMyPe();
	LogEvent1(_CHARM_LANG_ID, _E_BEGIN_UNPACK, 1, iData); 
#endif
}

void charm_endUnpack(void)
{
#if CMK_TRACE_ENABLED
	int iData[1];
	iData[0] = CkMyPe();
	LogEvent1(_CHARM_LANG_ID, _E_END_UNPACK, 1, iData); 
#endif
}


